/**
 * 报表设计公司(2011)
 */
package com.reportgear.designer.pane.style;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import net.abbp.report.context.ReportContext;
import net.abbp.report.model.Cell;
import net.abbp.report.model.cell.style.FontStyle;
import net.abbp.report.view.GridView;

import com.reportgear.core.swing.pane.base.JBasePane;
import com.reportgear.designer.ui.base.ColorSelectionPane;
import com.reportgear.designer.ui.base.JLineComboBox;
import com.reportgear.designer.ui.base.JNumberField;
import com.reportgear.designer.util.GUIConstants;
import com.reportgear.report.context.DefaultValues;
import com.reportgear.report.view.grid.util.GraphHelper;

/**
 * @version 1.0 2011-3-24
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since ANNCSR 2.0
 */
public class ReportFontPane extends JBasePane implements ICellStyle {

    private JTextField familyField;
    private JList familyList;
    private JNumberField sizeField;
    private JList sizeList;
    private JTextField styleField;
    private JList styleList;
    private ColorSelectionPane foregroundColorPane;
    private JLineComboBox underlineCombo;
    // private JCheckBox isStrikethroughCheckBox;
    // private JCheckBox isShadowCheckBox;
    // private JCheckBox isSuperscriptCheckBox;
    // private JCheckBox isSubscriptCheckBox;
    private PreivewArea preview;
    private EventListenerList eventChangeList = new EventListenerList();
    ActionListener actionListener = new ActionListener() {

        public void actionPerformed(ActionEvent paramActionEvent) {
            fireStateChanged();
        }
    };
    ChangeListener changeListener = new ChangeListener() {

        public void stateChanged(ChangeEvent paramChangeEvent) {
            fireStateChanged();
        }
    };
    ListSelectionListener listSelectionListener = new ListSelectionListener() {

        public void valueChanged(ListSelectionEvent paramListSelectionEvent) {
            fireStateChanged();
        }
    };
    DocumentListener documentListener = new DocumentListener() {

        public void changedUpdate(DocumentEvent paramDocumentEvent) {
            fireStateChanged();
        }

        public void insertUpdate(DocumentEvent paramDocumentEvent) {
            fireStateChanged();
        }

        public void removeUpdate(DocumentEvent paramDocumentEvent) {
            fireStateChanged();
        }
    };

    public ReportFontPane() {
        initComponents();
    }

    protected void initComponents() {
        this.setLayout(new BorderLayout());
        this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        JPanel fontInfoPane = new JPanel();
        fontInfoPane.setLayout(new BoxLayout(fontInfoPane, 0));
        this.familyField = new JTextField();
        JPanel fontPane =
                createTextFieldListPane("名字", this.familyField, this.familyList =
                        new JList(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()));
        this.familyField.setEditable(false);
        this.familyList.setVisibleRowCount(4);
        this.familyList.addListSelectionListener(this.listSelectionListener);

        fontInfoPane.add(fontPane);
        fontInfoPane.add(Box.createHorizontalStrut(6));

        this.styleField = new JTextField();
        JPanel stylePane =
                createTextFieldListPane("样式", this.styleField, this.styleList =
                        new JList(new String[]{"普通", "加粗", "斜体", "加粗斜体"}));
        this.styleField.setEditable(false);
        this.styleList.setVisibleRowCount(4);
        this.styleList.addListSelectionListener(this.listSelectionListener);

        fontInfoPane.add(stylePane);
        fontInfoPane.add(Box.createHorizontalStrut(6));

        this.sizeField = new JNumberField();
        JPanel sizePane =
                createTextFieldListPane("大小", this.sizeField, this.sizeList =
                        new JList(new Integer[]{6, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72}));
        this.sizeField.setMaxDecimalLength(0);
        this.sizeField.getDocument().addDocumentListener(this.documentListener);
        this.sizeField.getDocument().addDocumentListener(new DocumentListener() {

            public void changedUpdate(DocumentEvent paramDocumentEvent) {
                updatePreviewLabel();
            }

            public void insertUpdate(DocumentEvent paramDocumentEvent) {
                updatePreviewLabel();
            }

            public void removeUpdate(DocumentEvent paramDocumentEvent) {
                updatePreviewLabel();
            }
        });
        this.sizeList.setVisibleRowCount(4);
        this.sizeList.addListSelectionListener(this.listSelectionListener);
        fontInfoPane.add(sizePane);

        add(fontInfoPane, BorderLayout.NORTH);

        JPanel pane = new JPanel();
        add(pane, BorderLayout.CENTER);
        pane.setLayout(new BorderLayout(4, 4));

        // JPanel effectPane = new JPanel();
        // pane.add(effectPane, BorderLayout.WEST);
        // effectPane.setLayout(new BorderLayout());
        // effectPane.setBorder(BorderFactory.createTitledBorder("特殊效果"));
        // JPanel effectInnerPane = new JPanel();
        // effectPane.add(effectInnerPane, BorderLayout.NORTH);
        // effectInnerPane.setLayout(new GridLayout(4, 1));
        // this.isStrikethroughCheckBox = new JCheckBox("删除线");
        // this.isStrikethroughCheckBox.addChangeListener(this.changeListener);
        // this.isStrikethroughCheckBox.setMnemonic('K');
        // this.isShadowCheckBox = new JCheckBox("阴影");
        // this.isShadowCheckBox.addChangeListener(this.changeListener);
        // this.isShadowCheckBox.setMnemonic('S');
        // this.isSuperscriptCheckBox = new JCheckBox("上标");
        // this.isSuperscriptCheckBox.addChangeListener(this.changeListener);
        // this.isSuperscriptCheckBox.setMnemonic('E');
        // this.isSubscriptCheckBox = new JCheckBox("下标");
        // this.isSubscriptCheckBox.addChangeListener(this.changeListener);
        // this.isSubscriptCheckBox.setMnemonic('B');
        // effectInnerPane.add(getLeftJustPane(this.isStrikethroughCheckBox));
        // effectInnerPane.add(getLeftJustPane(this.isShadowCheckBox));
        // effectInnerPane.add(getLeftJustPane(this.isSuperscriptCheckBox));
        // effectInnerPane.add(getLeftJustPane(this.isSubscriptCheckBox));

        JPanel pane1 = new JPanel();
        pane.add(pane1, BorderLayout.CENTER);
        pane1.setLayout(new BorderLayout());
        JPanel pane2 = new JPanel();
        pane1.add(pane2, BorderLayout.NORTH);
        pane2.setLayout(new GridLayout(1, 2, 0, 0));
        JPanel underlinePane = new JPanel();
        pane2.add(underlinePane);
        underlinePane.setBorder(BorderFactory.createTitledBorder("下划线"));
        underlinePane.setLayout(new BorderLayout());
        this.underlineCombo = new JLineComboBox(GUIConstants.UnderlineStyleArray);
        this.underlineCombo.addActionListener(this.actionListener);
        underlinePane.add(this.underlineCombo, BorderLayout.CENTER);
        JPanel forecolorPane = new JPanel();
        pane2.add(forecolorPane);
        forecolorPane.setLayout(new BorderLayout());
        forecolorPane.setBorder(BorderFactory.createTitledBorder("字体颜色"));
        this.foregroundColorPane = new ColorSelectionPane(120);
        this.foregroundColorPane.addColorChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent paramChangeEvent) {
                ReportFontPane.this.fireStateChanged();
            }
        });
        forecolorPane.add(this.foregroundColorPane, BorderLayout.CENTER);
        this.preview = new PreivewArea();
        this.preview.setBorder(BorderFactory.createTitledBorder("预览"));
        pane1.add(this.preview, BorderLayout.CENTER);

        // this.isSuperscriptCheckBox.addChangeListener(this.changeListener);
        // this.isSuperscriptCheckBox.addChangeListener(new ChangeListener() {
        //
        // public void stateChanged(ChangeEvent paramChangeEvent) {
        // if (!(isSuperscriptCheckBox.isSelected())) {
        // return;
        // }
        // isSubscriptCheckBox.setSelected(false);
        // }
        // });
        // this.isSubscriptCheckBox.addChangeListener(this.changeListener);
        // this.isSubscriptCheckBox.addChangeListener(new ChangeListener() {
        //
        // public void stateChanged(ChangeEvent paramChangeEvent) {
        // if (!(isSubscriptCheckBox.isSelected())) {
        // return;
        // }
        // isSuperscriptCheckBox.setSelected(false);
        // }
        // });
    }

    public void addChangeListener(ChangeListener listener) {
        this.eventChangeList.add(ChangeListener.class, listener);
    }

    public void fireStateChanged() {
        Object[] arrayOfObject = this.eventChangeList.getListenerList();
        ChangeEvent localChangeEvent = null;
        for (int i = arrayOfObject.length - 2; i >= 0; i -= 2) {
            if (arrayOfObject[i] != ChangeListener.class) {
                continue;
            }
            if (localChangeEvent == null) {
                localChangeEvent = new ChangeEvent(this);
            }
            ((ChangeListener) arrayOfObject[(i + 1)]).stateChanged(localChangeEvent);
        }
    }

    private JPanel getLeftJustPane(JComponent c) {
        JPanel pane = new JPanel();
        pane.setLayout(new BorderLayout());
        pane.add(c, BorderLayout.CENTER);
        pane.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 0));

        return pane;
    }

    public void populate(FontStyle reportFont) {
        this.familyList.setSelectedValue(reportFont.getName(), true);
        this.familyField.setText(reportFont.getName());
        this.styleList.setSelectedIndex(reportFont.getStyle());
        this.styleField.setText(reportFont.getFontName());
        this.sizeList.setSelectedValue(new Integer(reportFont.getSize()), true);
        this.sizeField.setValue(reportFont.getSize());
        this.foregroundColorPane.setColor(reportFont.getForeground());
        this.underlineCombo.setSelectedLineStyle(reportFont.getUnderline());
        // this.isStrikethroughCheckBox.setSelected(reportFont.isStrikethrough());
        // this.isShadowCheckBox.setSelected(reportFont.isShadow());
        // this.isSuperscriptCheckBox.setSelected(reportFont.isSuperscript());
        // this.isSubscriptCheckBox.setSelected(reportFont.isSubscript());
        ListHandler localListHandler = new ListHandler();
        this.familyList.addListSelectionListener(localListHandler);
        this.styleList.addListSelectionListener(localListHandler);
        this.sizeList.addListSelectionListener(localListHandler);
        ActionListener listener1 = new ActionListener() {

            public void actionPerformed(ActionEvent evt) {
                updatePreviewLabel();
            }
        };
        // this.isStrikethroughCheckBox.addActionListener(listener1);
        // this.isShadowCheckBox.addActionListener(listener1);
        // this.isSuperscriptCheckBox.addActionListener(listener1);
        // this.isSubscriptCheckBox.addActionListener(listener1);
        this.underlineCombo.addItemListener(new ItemListener() {

            public void itemStateChanged(ItemEvent evt) {
                updatePreviewLabel();
            }
        });
        this.foregroundColorPane.addColorChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent evt) {
                updatePreviewLabel();
            }
        });
        updatePreviewLabel();
    }

    public FontStyle update() {
        return FontStyle.getInstance(this.familyField.getText(),
                                     this.styleList.getSelectedIndex(),
                                     (int) this.sizeField.getValue(),
                                     this.foregroundColorPane.getColor(),
                                     this.underlineCombo.getSelectedLineStyle());
    }

    private JPanel createTextFieldListPane(String labelStr, JTextField textField, JList listInfo) {
        GridBagLayout layout = new GridBagLayout();
        JPanel retPane = new JPanel(layout);
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.fill = GridBagConstraints.BOTH;
        constraints.weightx = 1.0D;
        JLabel label = new JLabel(labelStr);
        layout.setConstraints(label, constraints);
        retPane.add(label);
        constraints.gridy = 1;
        Component c = Box.createVerticalStrut(0);
        layout.setConstraints(c, constraints);
        retPane.add(c);
        constraints.gridy = 2;
        layout.setConstraints(textField, constraints);
        retPane.add(textField);
        constraints.gridy = 3;
        c = Box.createVerticalStrut(2);
        layout.setConstraints(c, constraints);
        retPane.add(c);
        constraints.gridy = 4;
        constraints.gridheight = 0;
        constraints.weighty = 1.0D;
        JScrollPane scrollPane = new JScrollPane(listInfo);
        layout.setConstraints(scrollPane, constraints);
        retPane.add(scrollPane);

        return retPane;
    }

    private void updatePreviewLabel() {
        this.preview.setPaintFont(update());
    }

    public void populateCellStyle(GridView workSheet) {
        FontStyle reportFont = workSheet.getActiveCellStyle().getFontStyle();

        if (reportFont == null) {
            DefaultValues defValues = ReportContext.INSTANCE.getDefaultValues();
            populate(defValues.getReportFont());
        } else {
            populate(reportFont);
        }
    }

    public void updateCellStyle(GridView workSheet) {
        FontStyle font = update();
        if (font.equals(workSheet.getActiveCellStyle().getFontStyle())) {
            return;
        }

        List<Cell> cells = workSheet.getSelectedCells();
        for (Cell cell : cells) {
            cell.setStyle(cell.getStyle().deriveReportFont(font));
        }
    }

    class PreivewArea extends JComponent {

        private String paintText = "Report中国";
        private FontStyle paintFont = null;

        public void setPaintFont(FontStyle reportFont) {
            this.paintFont = reportFont;
            repaint();
        }

        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            Dimension dim = getSize();
            g2.setColor(getBackground());
            GraphHelper.fillRect(g2, 0.0D, 0.0D, dim.width, dim.height);
            if (this.paintFont == null) {
                return;
            }
            FontMetrics fm = getFontMetrics(this.paintFont);
            g2.setColor(this.paintFont.getForeground());
            g2.setFont(this.paintFont);
            int x1 = (dim.width - fm.stringWidth(this.paintText)) / 2;
            int x2 = (dim.width + fm.stringWidth(this.paintText)) / 2;
            int h = (dim.height - fm.getHeight()) / 2 + fm.getAscent();
            GraphHelper.drawLine(g2, 4.0D, h, x1 - 8, h, 1);
            GraphHelper.drawString(g2, this.paintText, x1, h);
            GraphHelper.drawLine(g2, x2 + 8, h, dim.width - 4, h, 1);
        }
    }

    class ListHandler implements ListSelectionListener {

        public void valueChanged(ListSelectionEvent evt) {
            Object o2;
            Object o1 = evt.getSource();
            if (o1 == familyList) {
                o2 = (String) familyList.getSelectedValue();
                if (o2 != null) {
                    familyField.setText((String) o2);
                }
            } else if (o1 == sizeList) {
                o2 = (Integer) sizeList.getSelectedValue();
                if (o2 != null) {
                    sizeField.setValue(((Integer) o2).intValue());
                }
            } else if (o1 == styleList) {
                o2 = (String) styleList.getSelectedValue();
                if (o2 != null) {
                    styleField.setText((String) o2);
                }
            }
            updatePreviewLabel();
        }
    }

    public static void main(String[] args) {
        ReportFontPane pane = new ReportFontPane();
        pane.showDialog(null, "测试", 600, 500);
    }
}
